package com.example.requestheaders.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import com.example.requestheaders.base.BaseAuth;
import com.nimbusds.jose.JWSObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import com.example.requestheaders.wrapper.CustomHttpServletRequestWrapper;
import org.springframework.core.MethodParameter;
import org.springframework.util.ClassUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;

/**
 * @version 1.0.0
 * @description:
 * @author: guorf
 * @time: 2021/12/27 11:31
 */
@Slf4j
public class CustomInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        pushAuthBody(request, handlerMethod);

        return true;
    }

    private void pushAuthBody(HttpServletRequest request, HandlerMethod handlerMethod) {
        try{
            String token = request.getHeader("token");
            log.debug("token======{}", token);
            log.debug("method ==== {}", request.getMethod());
            JSONObject payload = parseToken(token);
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if(ArrayUtils.isEmpty(methodParameters)) {
                return;
            }
            for (MethodParameter methodParameter : methodParameters) {
                Class clazz = methodParameter.getParameterType();
                if(ClassUtils.isAssignable(BaseAuth.class, clazz)){
                    if(request instanceof CustomHttpServletRequestWrapper){
                        CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
                        String body = requestWrapper.getBody();
                        JSONObject param = new JSONObject();
                        if(StrUtil.isNotBlank(body)) {
                            param = JSONUtil.parseObj(body);
                        }
                        String username = payload.get("sub").toString();
                        param.putOnce("username", username);
//                        param.put("userName", Objects.isNull(userName) ? null : URLDecoder.decode(userName, "UTF-8"));
                        if ("POST".equals(request.getMethod())) {
                            param.putOnce("createUser", username);
                            param.putOnce("updateUser", username);
                        } else if ("PUT".equals(request.getMethod()) || "DELETE".equals(request.getMethod())) {
                            param.putOnce("updateUser", username);
                        }
                        requestWrapper.setBody(JSONUtil.toJsonStr(param));
                        requestWrapper.addHeader("username", username);
                    }
                }
            }
        }catch (Exception e){
            log.warn("fill auth info to request body Error ", e);
        }
    }

    /**
     * @description TODO:解析token
     * @param token
     * @return: cn.hutool.json.JSONObject
     * @author: guorf
     * @time: 2021/12/27 15:24
     */
    private JSONObject parseToken(String token) throws ParseException {
        String payload = JWSObject.parse(token.substring(7)).getPayload().toString();
        JSONObject payloadJson = JSONUtil.toBean(payload, JSONObject.class);
        log.debug("sub is {}", payloadJson.get("sub"));
        return payloadJson;
    }
}
